package eteam.aps.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import eteam.aps.client.CommonClient;
import eteam.aps.common.component.GetOrderNumber;
import eteam.aps.common.component.LoginUserRedisService;
import eteam.aps.common.constant.ProductType;
import eteam.aps.common.entity.ParentEntity;
import eteam.aps.common.exceptions.BusinessException;
import eteam.aps.common.helper.Assert;
import eteam.aps.common.helper.Helper;
import eteam.aps.common.helper.JsonPage;
import eteam.aps.mapper.*;
import eteam.aps.model.dto.SaleDto;
import eteam.aps.model.dto.SaleScanDto;
import eteam.aps.model.entity.sale.SaleOrder;
import eteam.aps.model.entity.sale.SaleOrderBll;
import eteam.aps.model.entity.sale.SaleOrderScan;
import eteam.aps.model.entity.sale.SaleScanAlready;
import eteam.aps.model.export.KV;
import eteam.aps.model.vo.product_number.ProductNumberOrderVo;
import eteam.aps.model.vo.sale.SaleOrderDetailsVo;
import eteam.aps.model.vo.sale.SaleOrderScanDto;
import eteam.aps.model.vo.sale.SaleOrderVo;
import eteam.aps.service.SaleOrderService;
import eteam.aps.systeminterface.model.vo.Worksheets;
import eteam.aps.zn.ZNApiConstant;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 销售单 ServiceImpl 实现类
 *
 * @author Ll
 * @since 2024/01/09
 */
@Service
@AllArgsConstructor
public class SaleOrderServiceImpl extends ServiceImpl<SaleOrderMapper, SaleOrder> implements SaleOrderService {

    private final SaleOrderBllMapper bilMapper;

    private final SaleOrderScanMapper saleOrderScanMapper;

    private final SaleScanAlreadyMapper alreadyMapper;

    private final ProductNumberMapper productMapper;

    private final CommonClient commonClient;

    private final LoginUserRedisService loginUserRedisService;

    @Override
    @Transactional
    public void saveOrder(SaleDto sale) throws Exception {
        String uid = loginUserRedisService.getUser().getFuserid();
        SaleOrder order = sale.getSale();
        Helper.setDefaultAddValue(order, uid);
        // 获取单别信息
        Worksheets worksheets = commonClient.selectSheetPrefix(ZNApiConstant.OGC);
        // 获取起始单号
        String orderNumber = GetOrderNumber.getOrderNumber(worksheets, baseMapper.selectMaxOrderNumber());
        // 设置流程编码
        order.setfWorksheetCode(ZNApiConstant.OGC);
        // 设置流程名称
        order.setfWorksheetName(ZNApiConstant.OGN);
        // 设置单号
        order.setfOrderNumber(orderNumber);
        // 设置单据日期
        order.setfOrderDate(LocalDate.now());
        baseMapper.insert(order);
        List<SaleOrderBll> bil = sale.getSaleBil();
        if (bil != null && !bil.isEmpty()) {
            AtomicInteger no = new AtomicInteger(0);
            bil.forEach(data -> {
                Assert.isBlank(data.getfInvCode(), "物料编号不能为空！");
                Assert.isTrue(data.getfSendNum() == null || data.getfSendNum().compareTo(BigDecimal.ZERO) == 0, "发货数不能为空且发货数不能为0！");
            });
            bil.forEach(data -> {
                data.setfSeqNo(no.incrementAndGet());
                data.setfDtlId(orderNumber);
                Helper.setDefaultAddValue(data, uid);
            });
            bilMapper.batchInsert(sale.getSaleBil());
        }
    }

    @Override
    @Transactional
    public void confirmSaleBar(SaleScanDto scan) throws Exception {
        // 查询发货单物料信息
        SaleOrderBll bll = bilMapper.selectOne(new LambdaQueryWrapper<SaleOrderBll>().select(SaleOrderBll::getfDtlId, SaleOrderBll::getfScanNum, SaleOrderBll::getfSendNum, SaleOrderBll::getfId).eq(SaleOrderBll::getfDtlId, scan.getOrderNumber()).eq(SaleOrderBll::getfInvCode, scan.getInvCode()));
        if (bll == null) throw new BusinessException("暂无物料信息！");
        List<String> bar = scan.getBar();
        BigDecimal select = BigDecimal.valueOf(bar.size());
        BigDecimal sendNum = bll.getfSendNum();
        BigDecimal scanNum = bll.getfScanNum();
        Assert.isTrue(select.add(scanNum).compareTo(sendNum) > 0, "所选择的产品数和已扫描数的和不能大于发货数！");
        // 修改库存
        bilMapper.update(bll, new LambdaUpdateWrapper<>(SaleOrderBll.class).set(SaleOrderBll::getfScanNum, select.add(scanNum)).eq(SaleOrderBll::getfDtlId, scan.getOrderNumber()).eq(SaleOrderBll::getfInvCode, scan.getInvCode()));
        String uid = loginUserRedisService.getUser().getFuserid();
        LocalDate now = LocalDate.now();
        // 修改产品状态 (发货)
        List<Map<String, Object>> mapList = new LinkedList<>();
        scan.getBar().forEach(res -> {
            Map<String, Object> mp = new HashMap<>(6);
            mp.put("processing", ProductType.DELIVERY);
            mp.put("modify", uid);
            mp.put("time", now);
            mp.put("bar", res);
            mp.put("orderCode", bll.getfDtlId());
            mapList.add(mp);
        });
        // 修改产品状态
        productMapper.batchUpdateProTypeByBarCode(mapList);
        // 添加提交记录
        List<SaleScanAlready> alreadyList = scan.getBar().stream().map(data -> {
            SaleScanAlready already = new SaleScanAlready();
            Helper.setDefaultAddValue(already, uid);
            already.setfDtlId(bll.getfId());
            already.setfBarCode(data);
            return already;
        }).collect(Collectors.toList());
        if (!alreadyList.isEmpty()) alreadyMapper.batchInsert(alreadyList);
    }

    @Override
    public List<ProductNumberOrderVo> selectSaleBar(Map<String, Object> map) {
        return productMapper.selectSaleBar(map);
    }

    @Override
    public JsonPage<SaleOrderVo> selectPage(Map<String, Object> query, int page, int size) {
        int count = baseMapper.selectCountByQuery(query);
        if (count <= 0) return JsonPage.builder(page, size, count, Collections.emptyList());
        query.put("offSize", (page - 1) * size);
        query.put("size", size);
        List<SaleOrderVo> list = baseMapper.selectPageByQuery(query);
        return JsonPage.builder(page, size, count, list);
    }

    @Override
    public List<SaleOrderDetailsVo> selectOrderDetails(String order) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("state", ParentEntity.FSTATE_DELETED);
        map.put("dtl", order);
        List<SaleOrderDetailsVo> blls = bilMapper.selectDetailsList(map);
        if (blls.isEmpty()) throw new BusinessException("暂无数据！");
        return blls;
    }

//    @Override
//    public List<SaleAlreadyVo> selectOrderProductDetails(String orderDetailId) {
//        Map<String, Object> map = new HashMap<>(2);
//        map.put("state", ParentEntity.FSTATE_DELETED);
//        map.put("dtl", orderDetailId);
//        return alreadyMapper.selectDetailsList(map);
//    }

    @Override
    public List<KV<String, String>> selectOrderProductDetails(SaleOrderScanDto scan) {
        List<SaleOrderScan> saleOrderScans = saleOrderScanMapper.selectList(
                Wrappers.<SaleOrderScan>lambdaQuery()
                        .select(SaleOrderScan::getfId, SaleOrderScan::getfBarCode)
                        .eq(SaleOrderScan::getfSaleOrderCode, scan.getfSaleOrderCode())
                        .eq(SaleOrderScan::getfSepNo, scan.getfSeqNo())
                        .ne(SaleOrderScan::getfState, ParentEntity.FSTATE_DELETED)
        );
        return saleOrderScans.stream()
                .map(data -> new KV<>(data.getfId(), data.getfBarCode()))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void deleteSaleOrder(String fId) throws Exception {
        String uid = loginUserRedisService.getUser().getFuserid();
        LocalDateTime now = LocalDateTime.now();
        lambdaUpdate().set(SaleOrder::getfLastModifyUserId, uid)
                .set(SaleOrder::getfLastModifyTime, now)
                .set(SaleOrder::getfState, ParentEntity.FSTATE_DELETED)
                .eq(SaleOrder::getfId, fId).update();
        Map<String, Object> map = new HashMap<>(4);
        map.put("status", ParentEntity.FSTATE_DELETED);
        map.put("createUser", uid);
        map.put("createTime", now);
        map.put("id", fId);
        bilMapper.updateBySaleOrderId(map);
    }

    @Override
    public List<ProductNumberOrderVo> selectOrderInvProduct(Map<String, Object> map) {
        return productMapper.selectSaleBar(map);
    }

    private final static String PACKING = "纸";

    @Override
    @Transactional
    public void updateSaleOrder(SaleOrder order) throws Exception {
        String uid = loginUserRedisService.getUser().getFuserid();
        lambdaUpdate()
                .set(Helper.isNotEmpty(order.getfFulfillmentType()), SaleOrder::getfFulfillmentType, order.getfFulfillmentType())
                .set(Helper.isNotEmpty(order.getfLogisticsCode()), SaleOrder::getfLogisticsCode, order.getfLogisticsCode())
                .set(Helper.isNotEmpty(order.getfLogisticsName()), SaleOrder::getfLogisticsName, order.getfLogisticsName())
                .set(Helper.isNotEmpty(order.getfSendLogistics()), SaleOrder::getfSendLogistics, order.getfSendLogistics())
                .set(SaleOrder::getfLastModifyUserId, uid)
                .set(SaleOrder::getfLastModifyTime, LocalDateTime.now())
                .eq(SaleOrder::getfId, order.getfId()).update();
        // 修改运单号
        String orderNumber = order.getfOrderNumber();
        if (Helper.isEmpty(orderNumber)) {
            SaleOrder one = lambdaQuery()
                    .select(SaleOrder::getfOrderNumber)
                    .eq(SaleOrder::getfId, order.getfId())
                    .one();
            if (one != null) orderNumber = one.getfOrderNumber();
        }
        if (Helper.isNotEmpty(orderNumber)) {
            bilMapper.update(new SaleOrderBll(),
                    Wrappers.<SaleOrderBll>lambdaUpdate()
                            .set(SaleOrderBll::getfPacking, PACKING)
                            .set(SaleOrderBll::getfOrderNumber, order.getfLogisticsCode())
                            .eq(SaleOrderBll::getfDtlId, orderNumber)
            );
        }
    }

    @Override
    @Transactional
    public void cancelOrder(SaleOrderScanDto scan) throws Exception {
        // 撤销
        String uid = loginUserRedisService.getUser().getFuserid();
        SaleOrderScan saleOrderScan = new SaleOrderScan();
        saleOrderScanMapper.update(
                saleOrderScan,
                Wrappers.<SaleOrderScan>lambdaUpdate()
                        .set(SaleOrderScan::getfState, ParentEntity.FSTATE_DELETED)
                        .set(SaleOrderScan::getfLastModifyUserId, uid)
                        .set(SaleOrderScan::getfLastModifyTime, LocalDateTime.now())
                        .eq(SaleOrderScan::getfBarCode, scan.getfBarCode())
        );
        // 修改数量
        bilMapper.update(new SaleOrderBll(),
                Wrappers.<SaleOrderBll>lambdaUpdate()
                        .setSql("fScanNum = fScanNum - 1")
                        .eq(SaleOrderBll::getfDtlId, scan.getfSaleOrderCode())
                        .eq(SaleOrderBll::getfSeqNo, scan.getfSeqNo())
        );
    }
}
